//
// Created by Win on 2016/7/15.
//
#include <stdlib.h>
#include <stdio.h>

#include "frcomm.h"
#include "frmem.h"
#include "frreport_comm.h"
#include "frbyte_buffer.h"
#include "frrmi_basetype.h"
#include "frrmi.h"


rmiDataChild* rmiNodeNew(void)
{
    rmiDataChild *p_out = NULL;

    p_out = (rmiDataChild *)frmalloc(sizeof(rmiDataChild));
    if(p_out == NULL)
        return NULL;

    memset(p_out, 0x00, sizeof(rmiDataChild));
    
    return p_out;
}


rmiDataParent* rmiHeadNew(void)
{
    rmiDataParent *p_out = NULL;

    p_out = (rmiDataParent *)frmalloc(sizeof(rmiDataParent));
    if(p_out == NULL)
        return NULL;

    memset(p_out, 0x00, sizeof(rmiDataParent));

    return p_out;
}

void rmiNodeFree(rmiDataChild *p_data)
{
    rmiDataChild *p_node = NULL;
    
    p_node = p_data;
    while (p_node)
    {
        p_data = p_node->next_node;
        frfree(p_node);
        
        p_node = p_data;
    }
    
    return;
    
}

void rmiHeadFree(rmiDataParent *p_head)
{
    rmiDataParent *p_parent_tmp = NULL;
    
    p_parent_tmp = p_head;
    
    while (p_parent_tmp)
    {
        p_head = p_parent_tmp->next;
        
        if(p_parent_tmp->p_name)
            frfree(p_parent_tmp->p_name);
        
        if(p_parent_tmp->p_object_type)
            frfree(p_parent_tmp->p_object_type);
        
        if(p_parent_tmp->child)
            rmiNodeFree(p_parent_tmp->child);
        
        frfree(p_parent_tmp);
        
        p_parent_tmp = p_head;
    }
    
    return;

}




/*
 * 一个 rmiDataParent 只可能存在一个 child
 */
int rmiDataAddChild(rmiDataParent **pp_rmi_head, rmiDataParent **pp_rmi_add)
{
    rmiDataChild *p_st_node = NULL;
    rmiDataChild *p_st_node_tmp = NULL;
    rmiDataParent *p_rmi_head = NULL, *p_rmi_add = NULL;

    if(pp_rmi_head == NULL || pp_rmi_add == NULL)
        return FR_FAIL;

    if(*pp_rmi_add == NULL)
        return FR_SUCC;

    p_rmi_head = *pp_rmi_head;
    p_rmi_add = *pp_rmi_add;
    
    if(p_rmi_head == NULL)
    {
        *pp_rmi_head = p_rmi_add;
        return FR_SUCC;
    }
    
    p_st_node = p_rmi_head->child;
    //第一个子节点
    if(p_st_node == NULL)
    {
        p_st_node = rmiNodeNew();
        if(p_st_node == NULL)
        {
            rmiHeadFree(p_rmi_add);
            *pp_rmi_add = NULL;
            return FR_FAIL;
        }

        p_st_node->head_node = p_st_node;
        p_st_node->tail_node = p_st_node;
        p_st_node->child = p_rmi_add;
        p_rmi_head->child = p_st_node;
        return FR_SUCC;
    }
    else
    {
        if(p_st_node->tail_node)
        {
            p_st_node_tmp = rmiNodeNew();
            if(p_st_node_tmp == NULL)
            {
                rmiHeadFree(p_rmi_add);
                *pp_rmi_add = NULL;
                return FR_FAIL;
            }

            p_st_node_tmp->child = p_rmi_add;
            p_st_node->tail_node->next_node = p_st_node_tmp;
            p_st_node->tail_node = p_st_node_tmp;

            return FR_SUCC;
        }
    }

    return FR_FAIL;
}

int rmiDataAddBrother(rmiDataParent **pp_rmi_head, rmiDataParent **pp_rmi_add)
{
    rmiDataParent *p_rmi_head = NULL, *p_rmi_add = NULL;

    if(pp_rmi_add == NULL || pp_rmi_head == NULL)
        return FR_FAIL;
    
    if(*pp_rmi_add == NULL)
        return FR_SUCC;
    
    p_rmi_head = *pp_rmi_head;
    p_rmi_add = *pp_rmi_add;
    
    //pp_rmi_head 为空
    if(p_rmi_head == NULL)
    {
        *pp_rmi_head = p_rmi_add;
        p_rmi_add->tail = p_rmi_add;
        return FR_SUCC;
    }
    else
    {
        p_rmi_head->tail->next = p_rmi_add;
        p_rmi_head->tail = p_rmi_add;
    }
    
    return FR_SUCC;
}

int object_writeNonProxy(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, int i_use_request
                         , int *p_i_deep, rmiDataParent **pp_rmi_head, rmiDataParent **pp_rmi_root, uint32_t *p_u32_passHandle, char *p_parent, char *p_prefix)
{
    uint8_t u8_flag = 0;
    int i_ret = 0;
    uint8_t hasWriteObjectData = 0, hasBlockExternalData = 0;
    uint8_t externalizable = 0, sflag = 0;
    uint8_t serializable, isEnum;
    uint64_t u64_serialVersionUID = 0;
    uint16_t u16_numFields = 0;
    uint8_t u8_tcode = 0;
    rmiDataParent *p_rmi_head = NULL, *p_rmi_head_tmp = NULL;


    if(p_st_data == NULL || p_st_body_data == NULL || p_i_deep == NULL || pp_rmi_head == NULL || p_u32_passHandle == NULL)
        return FR_FAIL;

//    out.writeUTF(name);
    //class name
    p_rmi_head = rmiHeadNew();
    if(p_rmi_head == NULL)
        return FR_FAIL;
    rmiDataAddBrother(pp_rmi_root, &p_rmi_head);
    
    p_rmi_head->p_name = readUTF(p_st_data);
    if(p_rmi_head->p_name == NULL)
        return FR_FAIL;
    
    p_rmi_head->passhandle = *p_u32_passHandle;
    
    (*p_u32_passHandle)++;
    //    out.writeLong(getSerialVersionUID());
    i_ret = bytebuff_get_long(p_st_data, 8, &u64_serialVersionUID, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_get_char(p_st_data, &u8_flag);
    if(i_ret == FR_FAIL)
        return FR_FAIL;


    hasWriteObjectData = (uint8_t)((u8_flag & SC_WRITE_METHOD) != 0);
    hasBlockExternalData = (uint8_t)((u8_flag & SC_BLOCK_DATA) != 0);
    externalizable = (uint8_t)((u8_flag & SC_EXTERNALIZABLE) != 0);
    sflag = (uint8_t)((u8_flag & SC_SERIALIZABLE) != 0);

    if (externalizable && sflag) {
//        frwarn("serializable and externalizable flags conflict");
        return FR_FAIL;
    }

    if(externalizable || sflag)
        serializable = 1;

    isEnum =(uint8_t) SC_ENUM & u8_flag;
    if(isEnum && u64_serialVersionUID != 0)
    {
//        frwarn("enum descriptor has non-zero serialVersionUID: %llu", (unsigned long long)u64_serialVersionUID);
        return FR_FAIL;
    }

    i_ret = bytebuff_get_short(p_st_data, 2, &u16_numFields, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(isEnum && u16_numFields)
    {
//        frwarn("enum descriptor has non-zero field count: %d", u16_numFields);
        return FR_FAIL;
    }

    while (u16_numFields)
    {
        i_ret = bytebuff_get_char(p_st_data, &u8_tcode);
        if(i_ret == FR_FAIL)
            return FR_FAIL;

        p_rmi_head_tmp = rmiHeadNew();
        if(p_rmi_head_tmp == NULL)
            return FR_FAIL;
        
        //fname
        p_rmi_head_tmp->p_name = readUTF(p_st_data);
        if(p_rmi_head_tmp->p_name == NULL)
        {
            rmiHeadFree(p_rmi_head_tmp);
            return FR_FAIL;
        }

        p_rmi_head_tmp->u8_tcode = u8_tcode;

        if(u8_tcode == 'L' || u8_tcode =='[')
        {
            i_ret = readTypeString(p_st_data, p_st_body_data, i_use_request, p_i_deep, &p_rmi_head_tmp, NULL, p_u32_passHandle, p_parent, p_prefix);
            if(i_ret == FR_FAIL)
            {
                rmiHeadFree(p_rmi_head_tmp);
                return FR_FAIL;
            }
        }
        rmiDataAddBrother(pp_rmi_root, &p_rmi_head_tmp);
        
        i_ret = rmiDataAddChild(&p_rmi_head, &p_rmi_head_tmp);
        if(i_ret == FR_FAIL)
            return FR_FAIL;
        

        u16_numFields--;
    }

    
    if(hasWriteObjectData)
        p_rmi_head->hasData = 1;

    if(hasBlockExternalData)
        p_rmi_head->hasBlockExternalData = 1;
    
    if(externalizable)
        p_rmi_head->externalizable = 1;
        
    
    *pp_rmi_head = p_rmi_head;

    return FR_SUCC;

}
